<?php
/**
 *
 *            ┏┓　　  ┏┓+ +
 *           ┏┛┻━━━━━┛┻┓ + +
 *           ┃         ┃ 　
 *           ┃   ━     ┃ ++ + + +
 *          ████━████  ┃+
 *           ┃　　　　　 ┃ +
 *           ┃　　　┻　　┃
 *           ┃　　　　　 ┃ + +
 *           ┗━┓　　　┏━┛
 *             ┃　　　┃　　　　
 *             ┃　　　┃ + + + +
 *             ┃　　　┃    Code is far away from bug with the alpaca protecting
 *             ┃　　　┃ + 　　　　        神兽保佑,代码无bug
 *             ┃　　　┃
 *             ┃　　　┃　　+
 *             ┃     ┗━━━┓ + +
 *             ┃         ┣┓
 *             ┃ 　　　　　┏┛
 *             ┗┓┓┏━━┳┓┏━┛ + + + +
 *              ┃┫┫  ┃┫┫
 *              ┗┻┛  ┗┻┛+ + + +
 * Created by PhpStorm.
 * User: weaponhsu
 * Date: 2019/2/2
 * Time: 10:19 AM
 */

namespace Task;

use swoole_server;
use youliPhpLib\Common\RequestHelper;

class AsyncServer
{
    public $server;
    public $log_path;
    public $server_log_path;

    public function __construct()
    {
        date_default_timezone_set("PRC");
        $this->log_path = realpath(__DIR__) . '/log/swoole_server' . date('Y-m-d', time()) . '.log';
        $this->server_log_path = realpath(__DIR__) . '/log/swoole_log' . date('Y-m-d', time()) . '.log';

        $this->server = new swoole_server('0.0.0.0', 19888);
        $this->server->set([
            'worker_num' => 1,
            'daemonize' => 1,
            'max_request' => 10000,
            'task_worker_num' => 1,
            'task_ipc_mode' => 3,
//            'log_file' => $this->log_path
            'log_file' => $this->server_log_path,
            'log_level' => SWOOLE_LOG_TRACE,
            'trace_flags' => SWOOLE_TRACE_ALL
        ]);

        $this->server->on('Receive', [$this, 'onReceive']);
        // bind callback
        $this->server->on('Task', [$this, 'onTask']);
        $this->server->on('Finish', [$this, 'onFinish']);
        $this->server->start();

    }

    public function onReceive(swoole_server $server, $fd, $from_id, $data ) {
        // 根据日期重新生成日志
        $this->log_path = realpath(__DIR__) . '/log/swoole_server' . date('Y-m-d', time()) . '.log';
        self::log($this->log_path, "Get Message From Client {$fd}:{$data}");
        $data_arr = json_decode($data, true);
        self::log($this->log_path, "Timeout {$fd}:{" . (isset($data_arr['timeout']) ? $data_arr['timeout'] : 'Nah') . "}");

        // send a task to task worker.
        /*if (! isset($data_arr['timeout']) || $data_arr['timeout'] == 0) {
            if ($data_arr['timeout'] == 'all') {
                $timer_id = $server->tick(60000, function () use (&$server, &$data, &$fd) {
                    $server->task($data);
                });
                self::log($this->log_path, "ticker stats timer_id{$timer_id}");
            } else
                $server->task($data);
        } else if (isset($data_arr['timeout'])) {
            $timer_id = $server->after($data_arr['timeout'] * 1000, function () use (&$server, &$data, &$fd) {
                $server->task($data);
            });
            self::log($this->log_path, "timer_id {$timer_id} stats {" . json_encode($server->stats()) . "}");
        }*/
        if (! isset($data_arr['timeout']) || $data_arr['timeout'] == 0) {
            $server->task($data);
        } else if (isset($data_arr['timeout'])) {
            if ($data_arr['timeout'] == 'all') {
                $timer_id = $server->tick(60000, function () use (&$server, &$data, &$fd) {
                    $server->task($data);
                });
                self::log($this->log_path, "ticker stats timer_id{$timer_id}");
            } else {
                $timer_id = $server->after($data_arr['timeout'] * 1000, function () use (&$server, &$data, &$fd) {
                    $server->task($data);
                });
                self::log($this->log_path, "timer_id {$timer_id} stats {" . json_encode($server->stats()) . "}");
            }
        }

    }

    public function onTask($server, $task_id, $from_id, $data) {
        self::log($this->log_path, "taskId: $task_id ");
        return $this->func($data);
    }

    public function onFinish($server, $task_id, $data) {
        self::log($this->log_path, "Task {$task_id} finish");
        self::log($this->log_path, "Result: {$data}");
    }

    public function func($data) {
        self::log($this->log_path, "func: $data");
        $data = json_decode($data, true);
        self::log($this->log_path, "url: " . $data['url']);

        self::log($this->log_path, "data: " . json_encode($data));
        $res = RequestHelper::curlRequest($data['url'],  http_build_query($data['param']), 'POST');
        if ($res instanceof \Exception)
            self::log($this->log_path, "res: " . $res->getMessage());
        else
            self::log($this->log_path, "res: " . $res[1]);
        return true;
    }

    static protected function log($log_path = null, $content = '') {
        if (!is_null($log_path)) {
            error_log('[' . date('Y-m-d H:i:s', time()) . '] - '.$content . "\r\n", 3, $log_path);
        }
    }

}

//$server = new AsynServer();
